﻿using System;
using System.Collections.Generic;
#if DEBUG
using System.Diagnostics;
#endif // #if DEBUG
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

using FRL.DebtChased.Repository;
using FRL.DebtChased.RichContentService;
using FRL.DebtChased.Silverlight.Extensions;

#if AGENTEDITOR
using FRL.DebtChased.AgentEditor;
#endif // #if AGENTEDITOR

#if CLIENTEDITOR
using FRL.DebtChased.ClientEditor;
using System.Text;
#endif // #if CLIENTEDITOR

#if CHASEWORKSPACE
using FRL.DebtChased.ChaseWorkspace;
#endif // #if CHASEWORKSPACE

namespace FRL.DebtChased.Silverlight.Controls
{

	/// <summary>
	/// Declaration of ContactAddressCtrl class
	/// </summary>
	public partial class ContactAddressCtrl : UserControl
	{

		/////////////////////////////////////////////////////////////
		// Delegates and events

		public event EventHandler<ChildCtrlContentChangeEventArg> ContentChanged;

		public event EventHandler DeleteButtonClicked;

		/////////////////////////////////////////////////////////////
		// Attributes

		private bool m_bBlockUpdates = true;

		private double m_dblMinimumHeight = 100;

		public bool ShowDeleteButton
		{
			get { return (butDelete.Visibility == System.Windows.Visibility.Visible); }
			set { butDelete.Visibility = (value ? Visibility.Visible : Visibility.Collapsed); }
		}

		private bool m_bAllowContraction = true;
		public bool AllowContraction
		{
			get { return m_bAllowContraction; }
			set { 
				m_bAllowContraction = value;
				if (!m_bAllowContraction)
				{
					butArrow.Visibility = System.Windows.Visibility.Collapsed;
					gridViewPanel.Visibility = System.Windows.Visibility.Collapsed;
					gridEditPanel.Visibility = System.Windows.Visibility.Visible;
					gridEditPanel.Opacity = 1;
					Grid.SetColumnSpan(
						gridEditPanel,
						Grid.GetColumnSpan(gridEditPanel) + 1
					);
					LayoutRoot.Height = LayoutRoot.MaxHeight;
				}
			}
		}

		private ContactTabCtrl ParentContactsTab
		{
			get { return this.FindParent(typeof(ContactTabCtrl)) as ContactTabCtrl; }
		}

		private int m_iContactAddressId = 0;
		public int ContactAddressId
		{
			get { return m_iContactAddressId; }
			set { m_iContactAddressId = value; }
		}

		private bool m_bIsExpandable = true;
		public bool bIsExpandable
		{
			get { return m_bIsExpandable; }
			set { m_bIsExpandable = value; }
		}

		/////////////////////////////////////////////////////////////
		// Construction

		public ContactAddressCtrl()
		{

			// Load xaml resources
			InitializeComponent();

			// Exit if in debug
			if (CachedData.Singleton.CountryNames == null)
				return;

			// Set controls - country
			drpCountry.StringList = CachedData.Singleton.CountryNames;

			// Set drop-downs
			drpCounty.StringList = CachedData.Singleton.ContactCounties;
			drpCounty.Category = Definitions.ReusableString_ContactCounties;

			// Setup animations
			animContractPanelLayoutRoot.Completed += new EventHandler(animContractPanelLayoutRoot_Completed);

			// Update the address
			_updateAddressTextBlock();

			// unblock events
			m_bBlockUpdates = false;

		}

		/////////////////////////////////////////////////////////////
		// Event handlers

		private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
		{

			// Fire event
			_fireContentChangedEvent(
				(sender == txtAddressLineA)
				||
				(sender == txtPostcode)
			);

			// Update address
			_updateAddressTextBlock();

		}

		private void butCopyAddress_Click(object sender, EventArgs e)
		{

			// Get contact id
			ContactCtrl contactCtrl = this.FindParent(typeof(ContactCtrl)) as ContactCtrl;
			int iContactId = contactCtrl.ContactId;

			// Get the addresses
			List<ContactAddressTransport> addressList = ParentContactsTab.GetAddressList(iContactId);

			// Show the window
			ContactCopyAddressWnd wnd = new ContactCopyAddressWnd(addressList);
			wnd.Closed += new EventHandler(ContactCopyAddressWnd_Closed);
			wnd.Show();

		}

		void ContactCopyAddressWnd_Closed(object sender, EventArgs e)
		{

			// Get the selected address
			ContactCopyAddressWnd wnd = sender as ContactCopyAddressWnd;
			if ((wnd.DialogResult ?? false) && (wnd.SelectedAddress != null))
			{

				// Set controls
				ContactAddressTransport address = wnd.SelectedAddress;
				txtAddressLineA.Text = address.AddressLineA ?? string.Empty;
				txtAddressLineB.Text = address.AddressLineB ?? string.Empty;
				txtAddressLineC.Text = address.AddressLineC ?? string.Empty;
				txtCity.Text = address.City ?? string.Empty;
				drpCounty.Text = address.County ?? string.Empty;
				txtPostcode.Text = address.Postcode ?? string.Empty;
				if (
					(!string.IsNullOrEmpty(address.CountryCode))
					&&
					(CachedData.Singleton.CountryMap.ContainsKey(address.CountryCode))
				)
					drpCountry.Text = CachedData.Singleton.CountryMap[address.CountryCode];
				else
					drpCountry.Text = "";

			}

		}

		private void butDelete_Click(object sender, EventArgs e)
		{

			// Option for user
			if (!App.PopupOption("Delete this address?"))
				return;

			// Send event back to parent
			if (DeleteButtonClicked != null)
				DeleteButtonClicked(this,e);

		}

		private void butArrow_Click(object sender, EventArgs e)
		{
#if DEBUG
			Debug.Assert(m_bAllowContraction);
#endif // #if DEBUG

			// If expanding...
			if (this.GetTrueHeight() < LayoutRoot.MaxHeight)
				ExpandPanel(true);
			else
				ExpandPanel(false);

		}

		void animContractPanelLayoutRoot_Completed(object sender, EventArgs e)
		{

			// Hide the edit panel
			gridEditPanel.Visibility = System.Windows.Visibility.Collapsed;
			
		}

		private void DropDown_TextChanged(object sender, RoutedEventArgs e)
		{

			// Fire event
			_fireContentChangedEvent(false);

			// Update address
			_updateAddressTextBlock();

		}

		private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
		{

			// Fire event
			_fireContentChangedEvent(false);

			// Update address
			_updateAddressTextBlock();

		}

		/////////////////////////////////////////////////////////////
		// Operations

		public void ExpandPanel(bool bExpandPanel)
		{
#if DEBUG
			Debug.Assert(m_bAllowContraction);
#endif // #if DEBUG

			// If expanding panel...
			if (bExpandPanel)
			{

				gridEditPanel.Visibility = System.Windows.Visibility.Visible;
				animExpandPanelLayoutRoot.To = LayoutRoot.MaxHeight;
				animExpandPanel.Begin();
				butArrow.IsUpsideDown = false;

			}
			else
			{

				// Start contracting
				animContractPanelLayoutRoot.To = m_dblMinimumHeight;
				animContractPanel.Begin();
				butArrow.IsUpsideDown = true;

			}

		}

		private void _updateAddressTextBlock()
		{

			// Build lines
			List<string> strLines = new List<string>();
			if(txtAddressLineA.Text.Length > 0)
				strLines.Add(txtAddressLineA.Text);
			if(txtAddressLineB.Text.Length > 0)
				strLines.Add(txtAddressLineB.Text);
			if(txtAddressLineC.Text.Length > 0)
				strLines.Add(txtAddressLineC.Text);
			if(txtCity.Text.Length > 0)
				strLines.Add(txtCity.Text);
			if(drpCounty.Text.Length > 0)
				strLines.Add(drpCounty.Text);
			if(txtPostcode.Text.Length > 0)
				strLines.Add(txtPostcode.Text);
			if(drpCountry.Text.Length > 0)
				strLines.Add(drpCountry.Text);

			// Check for no address
			if(strLines.Count==0)
				strLines.Add("[no address]");

			// Add or remove inlines
			int iRequiredCount = (strLines.Count * 2) - 1;
			while (iRequiredCount > tbAddress.Inlines.Count)
			{
				if ((tbAddress.Inlines.Count % 2) == 0)
					tbAddress.Inlines.Add(new Run());
				else
					tbAddress.Inlines.Add(new LineBreak());
			}
			while (iRequiredCount < tbAddress.Inlines.Count)
				tbAddress.Inlines.RemoveAt(0);

			// Set the inlines
			for (int i1 = 0; i1 < strLines.Count; i1++)
			{

				// Set run
				Run run = tbAddress.Inlines[i1 * 2] as Run;
#if DEBUG
				Debug.Assert(run != null);
#endif // #if DEBUG
				run.Text = strLines[i1];

			}

			// Update the minimum height
			m_dblMinimumHeight = tbAddress.Margin.Top + tbAddress.ActualHeight + tbAddress.Margin.Bottom +16;
			m_dblMinimumHeight = Math.Max(m_dblMinimumHeight, LayoutRoot.MinHeight);

		}

		private void _fireContentChangedEvent(bool bUpdateTabHeading)
		{

			// Shortcuts
			if (m_bBlockUpdates)
				return;
			if (ContentChanged == null)
				return;

			// Inform parent of change in textual content
			ContentChanged(
				this,
				new ChildCtrlContentChangeEventArg(bUpdateTabHeading)
			);

		}

		public void PreDisplay()
		{

			// Setup copy button
			_setupCopyButton();

		}

		private void _setupCopyButton()
		{

			// Shortcuts
			if (ParentContactsTab == null)
			{

				// Hide the copy button
				butCopyAddress.Visibility = System.Windows.Visibility.Collapsed;

			}
			else
			{

				// Get contact id
				ContactCtrl contactCtrl = this.FindParent(typeof(ContactCtrl)) as ContactCtrl;
				int iContactId = contactCtrl.ContactId;

				// Get the addresses
				List<ContactAddressTransport> addressList = ParentContactsTab.GetAddressList(iContactId);

				// Can the copy-address button be enabled
				butCopyAddress.IsEnabled = (addressList.Count > 0);
				butCopyAddress.Visibility = System.Windows.Visibility.Visible;

			}

		}

		public void Set( ContactAddressTransport address )
		{

			// block events
			m_bBlockUpdates = true;
			{

				// Set controls
				txtAddressLineA.Text = address.AddressLineA ?? string.Empty;
				txtAddressLineB.Text = address.AddressLineB ?? string.Empty;
				txtAddressLineC.Text = address.AddressLineC ?? string.Empty;
				txtCity.Text = address.City ?? string.Empty;
				drpCounty.Text = address.County ?? string.Empty;
				txtPostcode.Text = address.Postcode ?? string.Empty;
				if(
					(string.IsNullOrEmpty(address.CountryCode))
					||
					(!CachedData.Singleton.CountryMap.ContainsKey(address.CountryCode))
				)
					drpCountry.Text = string.Empty;
				else
					drpCountry.Text = CachedData.Singleton.CountryMap[address.CountryCode];

			}
			m_bBlockUpdates = false;

			// Retain the id
			this.ContactAddressId = address.ContactAddressId;

			// Update the address
			_updateAddressTextBlock();

			// Setup the copy button
			_setupCopyButton();

			// If panel is contracted, and size needs changing...
			if (
				(gridViewPanel.Visibility == System.Windows.Visibility.Visible)
				&&
				(gridViewPanel.GetTrueHeight() != m_dblMinimumHeight)
			)
				ExpandPanel(false);

		}

		public ContactAddressTransport Get(List<string> Errors)
		{

			// Declare return variable
			ContactAddressTransport Ftmp = new ContactAddressTransport();

			// Check controls
			if(
				(txtAddressLineA.Text.Length==0)
				&&
				(txtCity.Text.Length==0)
				&&
				(drpCounty.Text.Length==0)
				&&
				(txtPostcode.Text.Length==0)
			)
				Errors.Add("A contact address must have either a first address line, a city, a county or a postcode.");
			if (!drpCountry.IsContentGood)
				Errors.Add("Enter a valid country.");

			// Find the country code
			string strCountryCode = null;
			if (drpCountry.IsContentGood)
			{
				foreach(var di in CachedData.Singleton.CountryMap)
				{
					if(di.Value == drpCountry.Text)
					{
						strCountryCode = di.Key;
						break;
					}
				}
#if DEBUG
				Debug.Assert(strCountryCode != null);
#endif // #if DEBUG
			}

			// Update address members
			Ftmp.ContactAddressId = this.ContactAddressId;
			Ftmp.AddressLineA = txtAddressLineA.Text;
			Ftmp.AddressLineB = txtAddressLineB.Text;
			Ftmp.AddressLineC = txtAddressLineC.Text;
			Ftmp.City = txtCity.Text;
			Ftmp.County = drpCounty.Text;
			Ftmp.Postcode = txtPostcode.Text;
			Ftmp.CountryCode = strCountryCode;

			// Return variable
			return Ftmp;

		}

		public string ComposeTabHeading()
		{

			// Declare return variable
			string strFtmp;

			// Find a suitable address heading
			strFtmp = txtPostcode.Text.Trim();
			if (strFtmp.Length == 0)
			{
				if (txtAddressLineA.Text.Length > 0)
					strFtmp = txtAddressLineA.Text;
				else if (txtCity.Text.Length > 0)
					strFtmp = txtCity.Text;
				else
					strFtmp = "[address]";
			}

			// Return variable
			return strFtmp;

		}

	}

}
